#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/signal.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <soc/gpio.h>

MODULE_LICENSE("Dual BSD/GPL");


#define NDEVS 2

struct gpio_i2c_sccb_dev {
	unsigned int sda_pin;
	unsigned int scl_pin;
	int usec; // clock frequency
};

static struct gpio_i2c_sccb_dev devs[NDEVS] = {
	{
		.scl_pin = 127, //pd31,
		.sda_pin = 126, //pd30,
		.usec  = 10 // 100 khz
	},
	{
		.scl_pin = 159, //pe31,
		.sda_pin = 158, //pe30,
		.usec  = 10 // 100 khz
	}
};

static inline int gpio_get(int gpio)
{
	return gpio_get_value(gpio);
}

void gpio_set(int gpio)
{
	if(0 != gpio_direction_output(gpio, 1)) {
		printk("%s %d Error\n", __func__, __LINE__);
	}
}
void gpio_clr(int gpio)
{
	if(0 != gpio_direction_output(gpio, 0)) {
		printk("%s %d Error\n", __func__, __LINE__);
	}
}

/*
 *  * sends a start bit via I2C rountine.
 */

static void i2c_start_bit(int n)
{

	int i;
	gpio_set(devs[n].sda_pin);
	udelay(devs[n].usec);
	gpio_set(devs[n].scl_pin);
	udelay(devs[n].usec);

	gpio_clr(devs[n].sda_pin); //SCL 为高时SDA由高变低
	udelay(devs[n].usec);
}


/*  receives an acknowledge from I2C rountine.
 *
 *  @return value: 0--Ack received; 1--Nack received 接收到高电平表示从设备接收成功。
 *
 */
static unsigned char i2c_receive_ack(int n)
{
	unsigned char ack;

	// set sda line as input
	if(0 != gpio_direction_input(devs[n].sda_pin)) {
		printk("%s %d Error\n", __func__, __LINE__);
	}

	// have a rising clock to read data
	gpio_clr(devs[n].scl_pin);
	udelay(devs[n].usec);
	gpio_set(devs[n].scl_pin);
	udelay(devs[n].usec);

	// read ack value
	ack = gpio_get(devs[n].sda_pin);

	return ack;
}

/*
 *
 * sends an acknowledge over I2C rountine.
 * 发送高电平
 */
static void i2c_send_ack(int n)
{

	// let clk low to change data line
	gpio_clr(devs[n].scl_pin);
	gpio_clr(devs[n].sda_pin);

	// set data to low to send ack
	udelay(devs[n].usec);

	// set clk to high to send ack to device
	gpio_set(devs[n].scl_pin);
	udelay(devs[n].usec);

}
static void i2c_send_nack(int n)
{

	// let clk low to change data line
	gpio_clr(devs[n].scl_pin);
	gpio_set(devs[n].sda_pin);
	udelay(devs[n].usec);

	// set data to low to send ack

	// set clk to high to send ack to device
	gpio_set(devs[n].scl_pin);
	udelay(devs[n].usec);

}

/*
 * sends a character over I2C rountine.
 * @param  c: character to send
 */

static void i2c_send_byte(int n, unsigned char c)
{
	int i;


	for (i=0; i<8; i++)
	{
		gpio_clr(devs[n].scl_pin);

		if (c & (1<<(7-i)))//相应位为1
			gpio_set(devs[n].sda_pin);
		else               //相应位为0
			gpio_clr(devs[n].sda_pin);

		udelay(devs[n].usec);

		gpio_set(devs[n].scl_pin);
		udelay(devs[n].usec);
	}
}

/*
 *  receives a character from I2C rountine.
 *  @return value: character received
 */
static unsigned char i2c_receive_byte(int n)
{
	int value=0;
	int i;

	// set sda line as input
	if(0 != gpio_direction_input(devs[n].sda_pin)) {
		printk("%s %d Error\n", __func__, __LINE__);
	}

	for (i=0; i<8; i++)
	{
		value <<= 1;
		// a rise clock can receive a bit data
		gpio_clr(devs[n].scl_pin);
		udelay(devs[n].usec);
		gpio_set(devs[n].scl_pin);
		udelay(devs[n].usec);

		if (gpio_get(devs[n].sda_pin))
			value |= 1;

	//	udelay(devs[n].usec);
	}


	return value;
}

/*
 *  * sends a stop bit via I2C rountine.
 */
static void i2c_stop_bit(int n)
{

	/* actual stop bit */
	//gpio_clr(devs[n].scl_pin);
	gpio_clr(devs[n].sda_pin);
	udelay(devs[n].usec);
	
	//hold sck as high
	gpio_set(devs[n].scl_pin);
	udelay(devs[n].usec);

	// ada rise when scl high
	gpio_set(devs[n].sda_pin);//SCL为高时SDA由低变高
	udelay(devs[n].usec);
}

/*
 *  read data from the I2C bus by GPIO simulated of a device rountine.
 *  @param  devaddress:  address of the device
 *  @param  address: address of register within device
 *
 *  @return value: data from the device readed
 *
 */

unsigned char gpio_i2c_read(int n, unsigned char devaddress, unsigned char address)
{
    int rxdata;

    i2c_start_bit(n);

    i2c_send_byte(n, (unsigned char)(devaddress));
    if(1 == i2c_receive_ack(n)) {
		printk("%s %d NACK received\n", __func__, __LINE__);
	}

    i2c_send_byte(n, address);
    if(1 == i2c_receive_ack(n)) {
		printk("%s %d NACK received\n", __func__, __LINE__);
	}

    i2c_start_bit(n);

    i2c_send_byte(n, (unsigned char)(devaddress) | 1);
    if(1 == i2c_receive_ack(n)) {
		printk("%s %d NACK received\n", __func__, __LINE__);
	}

    rxdata = i2c_receive_byte(n);
    i2c_send_ack(n);

    i2c_stop_bit(n);

    return rxdata;
}

/*
 *  read data from the I2C bus by GPIO simulated of a digital camera device rountine.
 *
 *  @param  devaddress:  address of the device
 *  @param  address: address of register within device
 *
 */
unsigned char gpio_sccb_read(int n, unsigned char devaddress, unsigned char address)
{
	int rxdata;

	i2c_start_bit(n);
	i2c_send_byte(n, (unsigned char)(devaddress));
	if(1 == i2c_receive_ack(n)) {
		printk("%s %d NACK received\n", __func__, __LINE__);
	}
	i2c_send_byte(n, address);
	if(1 == i2c_receive_ack(n)) {
		printk("%s %d NACK received\n", __func__, __LINE__);
	}
	i2c_stop_bit(n);

	i2c_start_bit(n);
	i2c_send_byte(n, (unsigned char)(devaddress) | 1);
	if(1 == i2c_receive_ack(n)) {
		printk("%s %d NACK received\n", __func__, __LINE__);
	}
	rxdata = i2c_receive_byte(n);
	i2c_send_ack(n);
	i2c_stop_bit(n);

	return rxdata;
}
//EXPORT_SYMBOL(gpio_sccb_read);

/*
 *  writes data to a device on the I2C bus rountine.
 *
 *  @param  devaddress:  address of the device
 *  @param  address: address of register within device
 *  @param  data:   data for write to device
 *
 */

void gpio_i2c_write(int n, unsigned char devaddress, unsigned char address, unsigned char data)
{
	// start signal
    i2c_start_bit(n);

	// send device address
    i2c_send_byte(n, (unsigned char)(devaddress));
    i2c_receive_ack(n);

	// send register address
    i2c_send_byte(n, address);
    i2c_receive_ack(n);

	// send register value
    i2c_send_byte(n, data);
    i2c_stop_bit(n);
}

int gpio_i2c1_open(struct inode *inode, struct file *filp)
{
	int i;
	int addr;
	printk("%s called\n", __func__);

	printk("begin find a address\n");
	for(i = 0; i < 0xff; i++) {
		addr = i;
		i2c_start_bit(1);
		i2c_send_byte(1, (unsigned char)(addr));

		//i2c_receive_ack(1);

		if(0 == i2c_receive_ack(1)) {
			printk("receive ACK from 0x%x\n", addr);
		}  else {
			printk("receive NACK from 0x%x\n", addr);
		}

		i2c_stop_bit(1);
	}
	printk("finish find address\n");
	return 0;
}
static ssize_t	gpio_i2c1_read(struct file* filep, char __user* buf, size_t size, loff_t* ppos)
{
	printk("%s called\n", __func__);
	return 0;
}
static ssize_t	gpio_i2c1_write(struct file* filep, const char __user* buf, size_t size, loff_t* ppos)
{
	printk("%s called\n", __func__);
	return 0;
}
int gpio_i2c2_open(struct inode *inode, struct file *filp)
{
	printk("%s called\n", __func__);
	return 0;
}
static ssize_t	gpio_i2c2_read(struct file* filep, char __user* buf, size_t size, loff_t* ppos)
{
	printk("%s called\n", __func__);
	return 0;
}
static ssize_t	gpio_i2c2_write(struct file* filep, const char __user* buf, size_t size, loff_t* ppos)
{
	printk("%s called\n", __func__);
	return 0;
}
int gpio_sccb1_open(struct inode *inode, struct file *filp)
{
	printk("%s called\n", __func__);
	return 0;
}
static ssize_t	gpio_sccb1_read(struct file* filep, char __user* buf, size_t size, loff_t* ppos)
{
	printk("%s called\n", __func__);
	return 0;
}
static ssize_t	gpio_sccb1_write(struct file* filep, const char __user* buf, size_t size, loff_t* ppos)
{
	printk("%s called\n", __func__);
	return 0;
}
int gpio_sccb2_open(struct inode *inode, struct file *filp)
{
	printk("%s called\n", __func__);
	return 0;
}
static ssize_t	gpio_sccb2_read(struct file* filep, char __user* buf, size_t size, loff_t* ppos)
{
	printk("%s called\n", __func__);
	return 0;
}
static ssize_t	gpio_sccb2_write(struct file* filep, const char __user* buf, size_t size, loff_t* ppos)
{
	printk("%s called\n", __func__);
	return 0;
}

static struct file_operations i2c1_fops = {
	.owner = THIS_MODULE,
	.read  = gpio_i2c1_read,
	.write = gpio_i2c1_write,
	.open  = gpio_i2c1_open,
};
static struct file_operations i2c2_fops = {
	.owner = THIS_MODULE,
	.read  = gpio_i2c2_read,
	.write = gpio_i2c2_write,
	.open  = gpio_i2c2_open,
};
static struct file_operations sccb1_fops = {
	.owner = THIS_MODULE,
	.read  = gpio_sccb1_read,
	.write = gpio_sccb1_write,
	.open  = gpio_sccb1_open,
};
static struct file_operations sccb2_fops = {
	.owner = THIS_MODULE,
	.read  = gpio_sccb2_read,
	.write = gpio_sccb2_write,
	.open  = gpio_sccb2_open,
};

static dev_t gpio_i2c_dev1_t;
static dev_t gpio_i2c_dev2_t;
static dev_t gpio_sccb_dev1_t;
static dev_t gpio_sccb_dev2_t;

static struct cdev* gpio_i2c_dev1;
static struct cdev* gpio_i2c_dev2;
static struct cdev* gpio_sccb_dev1;
static struct cdev* gpio_sccb_dev2;

static struct class* gpio_i2c_sccb_class;

static int __init gpio_i2c_sccb_init(void)
{
	int i;
	char name[40];

	printk("%s called\n", __func__);



	// request all gpio
	for(i = 0; i < NDEVS; i++) {
		sprintf(name, "gpio-i2c-%d-scl", i);
		if(0 != gpio_request(devs[i].scl_pin, name)) {
			sprintf(name, "can't get gpio %d\n", devs[i].scl_pin);
			printk(name);
		}
		if(!gpio_is_valid(devs[i].scl_pin)) {
			printk("gpio %d not valid\n", devs[i].scl_pin);
		}

		sprintf(name, "gpio-i2c-%d-sda", i);
		if(0 != gpio_request(devs[i].sda_pin, name)) {
			sprintf(name, "can't get gpio %d\n", devs[i].sda_pin);
			printk(name);
		}
		if(!gpio_is_valid(devs[i].sda_pin)) {
			printk("gpio %d not valid\n", devs[i].sda_pin);
		}
	}

	// alloc device number

	alloc_chrdev_region(&gpio_i2c_dev1_t, 0, 1, "gpio_i2c_dev1");
	alloc_chrdev_region(&gpio_i2c_dev2_t, 0, 1, "gpio_i2c_dev2");
	alloc_chrdev_region(&gpio_sccb_dev1_t, 0, 1, "gpio_sccb_dev1");
	alloc_chrdev_region(&gpio_sccb_dev2_t, 0, 1, "gpio_sccb_dev2");

	// register i2c1 device
	gpio_i2c_dev1 = cdev_alloc();
	cdev_init(gpio_i2c_dev1, &i2c1_fops);
	gpio_i2c_dev1->owner = THIS_MODULE;
	gpio_i2c_dev1->ops = &i2c1_fops;
	cdev_add(gpio_i2c_dev1, gpio_i2c_dev1_t, 1);

	// register i2c2 device
	gpio_i2c_dev2 = cdev_alloc();
	cdev_init(gpio_i2c_dev2, &i2c2_fops);
	gpio_i2c_dev2->owner = THIS_MODULE;
	gpio_i2c_dev2->ops = &i2c2_fops;
	cdev_add(gpio_i2c_dev2, gpio_i2c_dev2_t, 1);

	// register sccb1 device
	gpio_sccb_dev1 = cdev_alloc();
	cdev_init(gpio_sccb_dev1, &sccb1_fops);
	gpio_sccb_dev1->owner = THIS_MODULE;
	gpio_sccb_dev1->ops = &sccb1_fops;
	cdev_add(gpio_sccb_dev1, gpio_sccb_dev1_t, 1);

	// register sccb2 device
	gpio_sccb_dev2 = cdev_alloc();
	cdev_init(gpio_sccb_dev2, &sccb2_fops);
	gpio_sccb_dev2->owner = THIS_MODULE;
	gpio_sccb_dev2->ops = &sccb2_fops;
	cdev_add(gpio_sccb_dev2, gpio_sccb_dev2_t, 1);

	// create device file
	gpio_i2c_sccb_class = class_create(THIS_MODULE, "gpio_i2c_sccb");
	if(IS_ERR(gpio_i2c_sccb_class)) {
		printk("Error in create gpio_i2c_sccb_class!\n");
	}


	device_create(gpio_i2c_sccb_class, NULL, gpio_i2c_dev1_t, NULL, "gpio-i2c-1");
	device_create(gpio_i2c_sccb_class, NULL, gpio_i2c_dev2_t, NULL, "gpio-i2c-2");
	device_create(gpio_i2c_sccb_class, NULL, gpio_sccb_dev1_t, NULL, "gpio-sccb-1");
	device_create(gpio_i2c_sccb_class, NULL, gpio_sccb_dev2_t, NULL, "gpio-sccb-2");


	return 0;
}

static void __exit gpio_i2c_sccb_exit(void)
{
	int i;

	printk("%s called\n", __func__);

	// free all gpio
	for(i = 0; i < NDEVS; i++) {
		gpio_free(devs[i].scl_pin);
		gpio_free(devs[i].sda_pin);
	}

	device_destroy(gpio_i2c_sccb_class, gpio_i2c_dev1_t);
	device_destroy(gpio_i2c_sccb_class, gpio_i2c_dev2_t);
	device_destroy(gpio_i2c_sccb_class, gpio_sccb_dev1_t);
	device_destroy(gpio_i2c_sccb_class, gpio_sccb_dev2_t);
	class_destroy(gpio_i2c_sccb_class);

	unregister_chrdev_region(gpio_i2c_dev1_t,  1);
	unregister_chrdev_region(gpio_i2c_dev2_t,  1);
	unregister_chrdev_region(gpio_sccb_dev1_t, 1);
	unregister_chrdev_region(gpio_sccb_dev2_t, 1);

	cdev_del(gpio_i2c_dev1);
	cdev_del(gpio_i2c_dev2);
	cdev_del(gpio_sccb_dev1);
	cdev_del(gpio_sccb_dev2);
}

module_init(gpio_i2c_sccb_init);
module_exit(gpio_i2c_sccb_exit);
